커맨드 패턴은 요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 매서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다. 어떤 로직에 대한 요청을 객체화 시킴으로써, 코드를 수정하거나 교체하기 쉽게 하고, 유지보수성을 높인다.
@Setter
@AllArgsConstructor
public class Lamp {
private boolean power;
public boolean isOn(){
return power;
}
}
@Setter
@AllArgsConstructor
public class AirConditioner {
private boolean power;
public boolean isOn(){
return power;
}
}
램프와 에어컨이 있다.
@Setter
@NoArgsConstructor
public class RemoteControl {
private Command command;
void pressButton() {
if (command != null){
command.execute();
}
}
}
그리고 리모컨이 있다.
우리는 램프와 에어컨, 두개의 장치를 하나의 리모컨으로 켜고 끄는 기능을 구현해볼 것이다.
public interface Command {
void execute();
}
실행할 Command들의 기반이 될 인터페이스를 만든다.
@RequiredArgsConstructor
public class LampOnCommand implements Command {
private final Lamp lamp;
@Override
public void execute() {
lamp.setPower(true);
}
}
@RequiredArgsConstructor
public class LampOffCommand implements Command {
private final Lamp lamp;
@Override
public void execute() {
lamp.setPower(false);
}
}
@RequiredArgsConstructor
public class AirConditionerOnCommand implements Command {
private final AirConditioner airConditioner;
@Override
public void execute() {
airConditioner.setPower(true);
}
}
@RequiredArgsConstructor
public class AirConditionerOffCommand implements Command {
private final AirConditioner airConditioner;
@Override
public void execute() {
airConditioner.setPower(false);
}
}
각 장치를 주입받아 상태를 변경시키는 로직을 수행하는 객체를 만들었다. 마치 일반적인 함수를 사용하는 것 처럼 객체를 생성할때 수정할, 또는 사용할 대상을 주입받아서 로직을 실행하는 것이 특징이다.
public class App {
public static void main(String[] args) {
AirConditioner airConditioner = new AirConditioner(false);
Lamp lamp = new Lamp(false);
RemoteControl remoteControl = new RemoteControl();
System.out.println("lamp");
System.out.println(lamp.isOn());
remoteControl.setCommand(new LampOnCommand(lamp));
remoteControl.pressButton();
System.out.println(lamp.isOn());
remoteControl.setCommand(new LampOffCommand(lamp));
remoteControl.pressButton();
System.out.println(lamp.isOn());
System.out.println("airConditioner");
System.out.println(airConditioner.isOn());
remoteControl.setCommand(new AirConditionerOnCommand(airConditioner));
remoteControl.pressButton();
System.out.println(airConditioner.isOn());
remoteControl.setCommand(new AirConditionerOffCommand(airConditioner));
remoteControl.pressButton();
System.out.println(airConditioner.isOn());
}
}
//실행 결과
lamp
false
true
false
airConditioner
false
true
false
위와 같이 커맨드 로직을 객체로 변환하여 remoteControl에 주입한 뒤 사용하면 된다. 요청을 객체의 형태로 캡슐화하였기 때문에 코드 실행중에 커맨드를 다른 객체로 변경하는 것도 가능하다.
이 링크로 가면 코드를 볼 수 있다.